/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
// pgifconv.hpp - GIF decompressor object.
//
// Author: Kenneth G. Maxwell
//
// Copyright (c) 1997-2000 Swell Software 
//              All Rights Reserved.
//
// Unauthorized redistribution of this source code, in whole or part,
// without the express written permission of Swell Software
// is strictly prohibited.
//
// Notes:
//
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef _PEGGIFCONVERT_
#define _PEGGIFCONVERT_

#define MAX_LWZ_BITS      12
#define GIF_CODE_STACK_SIZE 1024     // how deep is the opcode stack?
//#define GIF_CODE_STACK_SIZE 512
#define INTERLACE        0x40
#define LOCALCOLORMAP    0x80
#define GIFPEGUINT(a, b)          (((b)<<8)|(a))

/*--------------------------------------------------------------------------*/
// GIFHEAD structure- can be retrieved by application level
//      software during conversion if desired. There is one GIFHEAD
//      structure produced for each .gif file converted.
/*--------------------------------------------------------------------------*/
typedef struct {
    PEGUINT            Width;
    PEGUINT            Height;
    PEGUINT            Colors;
    PEGUBYTE           BackClrIndex;
    PEGCOLOR           Background;
    PEGUBYTE           AspectRatio;
    PEGUBYTE           IsGif89;
} GIF_HEADER;


/*--------------------------------------------------------------------------*/
// GIF_IMAGE structure. One of these structures is created for each
// image in a .gif file.
/*--------------------------------------------------------------------------*/
typedef struct {
    PEGINT             xOffset;
    PEGINT             yOffset;
    PEGUINT            Width;
    PEGUINT            Height;
    PEGUINT            Delay;
    PEGUBYTE           HasTrans;
    PEGUBYTE           TransColor;
    PEGUBYTE           InputFlag;
    PEGUBYTE           Disposal;
} GIF_IMAGE_INFO;


/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
class PegGifConvert : public PegImageConvert
{
    public:

        PegGifConvert(PEGUINT Id = 0);
        virtual ~PegGifConvert(void);

        void DestroyImages(void);

        GIF_HEADER *GetGifHeader(void) {return &mGifHead;}
        GIF_IMAGE_INFO *GetGifInfo(void) {return mpImageInfo;}

       #ifdef PEG_PIC_FILE_MODE
        virtual PEGBOOL GetImageInfo(PegFile *pSrc, PegImageInfo *info);
       #endif

        PEGBOOL ReadFrame();

       #ifdef PEG_PIC_FILE_MODE
        PEGBOOL ReadHeader(PegFile *pSrc);
        virtual PEGBOOL ReadImage(PegFile *pSrc, PEGINT Count = 10);
       #else
        PEGBOOL ReadHeader();
        virtual PEGBOOL ReadImage(PEGINT Count = 10);
       #endif

    private:

        PEGINT CheckStack(void);
        GIF_IMAGE_INFO *CurrentImageInfo(void);
        PEGINT DoExtension(PEGINT label);
        PEGINT GetCode(PEGINT code_size, PEGINT flag);
        PEGINT GetDataBlock(PEGUBYTE *pBuf);
        PEGINT LWZReadByte(PEGINT flag, PEGINT input_code_size);

        PEGINT ReadColorMap(PEGINT number, PEGUBYTE *pPalette);
        PEGBOOL ReadImage(PEGINT len, PEGINT height, PEGINT interlace);

       #if defined(PEG_IMAGE_SCALING)
        PEGBOOL ReadImageToSize(PEGINT len, PEGINT height, PEGINT interlace);
       #endif


        GIF_HEADER mGifHead;
        GIF_IMAGE_INFO *mpImageInfo;
        PEGSHORT mTable[2][(1<< MAX_LWZ_BITS)];
        PEGSHORT mStack[GIF_CODE_STACK_SIZE];
        PEGSHORT *mpStack;
        PEGUBYTE *pBuf;

        PEGINT mInfoCount;
        PEGINT mCurbit;
        PEGINT mLastbit;
        PEGINT mDone;
        PEGINT mLastByte;
        PEGINT mCodeSize;
        PEGINT mSetCodeSize;
        PEGINT mMaxCode;
        PEGINT mMaxCodeSize;
        PEGINT mFirstCode;
        PEGINT mOldCode;
        PEGINT mClearCode;
        PEGINT mEndCode;
        PEGBOOL mZeroDataBlock;
        PEGBOOL mFresh;
};

#endif

